/**
 * Created by Administrator on 2017/7/17.
 */

import java.lang.annotation.*;

/**
 * @author linruoyu
 *         重复注解
 *         正如我们看到的，这里有个使用@Repeatable( Filters.class )注解的注解类Filter，Filters仅仅是Filter注解的数组，
 *         但Java编译器并不想让程序员意识到Filters的存在。这样，接口Filterable就拥有了两次Filter（并没有提到Filter）注解。
 *         同时，反射相关的API提供了新的函数getAnnotationsByType()来返回重复注解的类型
 *         （请注意Filterable.class.getAnnotation( Filters.class )经编译器处理后将会返回Filters的实例）。
 *         <p>
 *         元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型，它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解：
 *         　　　　1.@Target,
 *         　　　　2.@Retention,
 *         　　　　3.@Documented,
 *         　　　　4.@Inherited
 *         　@Target：
 *         　　　@Target说明了Annotation所修饰的对象范围：Annotation可被用于 packages、types（类、接口、枚举、Annotation类型）、
 *         类型成员（方法、构造方法、成员变量、枚举值）、方法参数和本地变量（如循环变量、catch参数）。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。
 *         　　作用：用于描述注解的使用范围（即：被描述的注解可以用在什么地方）
 *         　　取值(ElementType)有：
 *         　　　　1.CONSTRUCTOR:用于描述构造器
 *         　　　　2.FIELD:用于描述域
 *         　　　　3.LOCAL_VARIABLE:用于描述局部变量
 *         　　　　4.METHOD:用于描述方法
 *         　　　　5.PACKAGE:用于描述包
 *         　　　　6.PARAMETER:用于描述参数
 *         　　　　7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
 *         Retention：
 *         　　@Retention定义了该Annotation被保留的时间长短：某些Annotation仅出现在源代码中，而被编译器丢弃；而另一些却被编译在class文件中；
 *         编译在class文件中的Annotation可能会被虚拟机忽略，而另一些在class被装载时将被读取（请注意并不影响class的执行，因为Annotation与class在使用上是被分离的）。
 *         使用这个meta-Annotation可以对 Annotation的“生命周期”限制。
 *         　　作用：表示需要在什么级别保存该注释信息，用于描述注解的生命周期（即：被描述的注解在什么范围内有效）
 *         　　取值（RetentionPoicy）有：
 *         　　　　1.SOURCE:在源文件中有效（即源文件保留）
 *         　　　　2.CLASS:在class文件中有效（即class保留）
 *         　　　　3.RUNTIME:在运行时有效（即运行时保留）
 **/
public class RepeatingAnnotations {
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Filters {
        Filter[] value();
    }

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Repeatable(Filters.class)
    public @interface Filter {
        String value();
    }

    ;

    @Filter("filter1")
    @Filter("filter2")
    public interface Filterable {
    }

    public static void main(String[] args) {
        for (Filter filter : Filterable.class.getAnnotationsByType(Filter.class)) {
            System.out.println(filter.value());
        }
    }
}
